package de.alt.rest.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import de.alt.rest.constants.NMAConstants;
import de.alt.rest.constants.NMAPriorityEnum;
import de.alt.rest.exception.NMAException;

/**
 * The Class NotifyMyAndroid.
 */
public class NotifyMyAndroid {

	/** The Constant log. */
	private static final Logger log = Logger.getLogger(NotifyMyAndroid.class.getName());

	/**
	 * Notify.
	 * 
	 * @param app
	 *            the app
	 * @param event
	 *            the event
	 * @param description
	 *            the description
	 * @param priority
	 *            the priority
	 * @param apiKey
	 *            the api key
	 * @throws NMAException
	 *             the nMA exception
	 */
	public void notify(String app, String event, String description, NMAPriorityEnum prio) throws NMAException {

		if ((app.length() == 0) || (app.length() > 256)) {
			throw new NMAException("App must have between 1 and 256 characters");
		}
		if ((event.length() == 0) || (event.length() > 1000)) {
			throw new NMAException("Event must have between 1 and 1000 characters");
		}
		if ((description.length() == 0) || (description.length() > 10000)) {
			throw new NMAException("Description must have between 1 and 10000 characters");
		}

		try {

			StringBuilder data = new StringBuilder();

			URL url = new URL(NMAConstants.DEFAULT_URL + NMAConstants.NOTIFY_PATH);

			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setDoOutput(true);
			connection.setRequestMethod(NMAConstants.METHOD_POST);
			connection.setUseCaches(false);
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

			// Setup the POST data
			addEncodedParameter(data, NMAConstants.MESSAGE_KEY_API_KEY, NMAConstants.API_KEY);
			addEncodedParameter(data, NMAConstants.MESSAGE_KEY_APP, app);
			addEncodedParameter(data, NMAConstants.MESSAGE_KEY_EVENT, event);
			addEncodedParameter(data, NMAConstants.MESSAGE_KEY_DESC, description);
			addEncodedParameter(data, NMAConstants.MESSAGE_KEY_PRIORITY, Integer.toString(prio.getValue()));

			// Buffers and Writers to send the data
			OutputStreamWriter writer;
			writer = new OutputStreamWriter(connection.getOutputStream());

			writer.write(data.toString());
			writer.flush();
			writer.close();
			BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

			if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {

				StringBuffer response = new StringBuffer();
				String line = null;
				while ((line = in.readLine()) != null) {
					response.append(line);
				}

				String resultStr = response.toString();
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = factory.newDocumentBuilder();
				InputSource inStream = new InputSource();
				inStream.setCharacterStream(new StringReader(resultStr));
				Document doc = db.parse(inStream);

				Element root = doc.getDocumentElement();

				if (root.getTagName().equals("nma")) {
					Node item = root.getFirstChild();
					String childName = item.getNodeName();
					if (!childName.equals("success")) {
						throw new NMAException(item.getFirstChild().getNodeValue());
					}
				}

			} else {
				throw new NMAException("HTTP Response code different from 200(OK)");
			}
		} catch (Exception e) {
			log.warning(e.getMessage());
			throw new NMAException(e.getMessage());
		}

	}

	/**
	 * Adds the encoded parameter.
	 * 
	 * @param sb
	 *            the sb
	 * @param name
	 *            the name
	 * @param value
	 *            the value
	 * @throws NMAException
	 *             the nMA exception
	 */
	private void addEncodedParameter(StringBuilder sb, String name, String value) throws NMAException {
		if (sb.length() > 0) {
			sb.append("&");
		}
		try {
			sb.append(URLEncoder.encode(name, NMAConstants.UTF_8_ENCODING));
			sb.append("=");
			sb.append(URLEncoder.encode(value, NMAConstants.UTF_8_ENCODING));
		} catch (UnsupportedEncodingException e) {
			log.warning(e.getMessage());
			throw new NMAException(e.getMessage());
		}
	}

}
